﻿namespace Tuxedo.Compile
{
	internal class LongConstant : Constant
	{
		public long Value { get; private set; }
		public override object ObjectValue { get { return this.Value; } }

		public LongConstant(long value)
		{
			this.Value = value;
		}

		public override bool IsZero { get { return this.Value == 0; } }
		
		public override Expression Add(Constant other)
		{
			if (other is LongConstant) return new LongConstant(this.Value + ((LongConstant)other).Value);
			if (other is IntegerConstant) return new LongConstant(this.Value + ((IntegerConstant)other).Value);
			if (other is DoubleConstant) return new DoubleConstant(this.Value + ((DoubleConstant)other).Value);
			if (other is FloatConstant) return new FloatConstant(this.Value + ((FloatConstant)other).Value);
			if (other is StringConstant) return new StringConstant(this.Value + ((StringConstant)other).Value);
			if (other is CharConstant) return new LongConstant(this.Value + ((CharConstant)other).Value);

			return base.Add(other);
		}

		public override Expression Subtract(Constant other)
		{
			if (other is LongConstant) return new LongConstant(this.Value - ((LongConstant)other).Value);
			if (other is IntegerConstant) return new LongConstant(this.Value - ((IntegerConstant)other).Value);
			if (other is DoubleConstant) return new DoubleConstant(this.Value - ((DoubleConstant)other).Value);
			if (other is FloatConstant) return new FloatConstant(this.Value - ((FloatConstant)other).Value);
			if (other is CharConstant) return new LongConstant(this.Value - ((CharConstant)other).Value);

			return base.Subtract(other);
		}

		public override Expression Multiply(Constant other)
		{
			if (other is LongConstant) return new LongConstant(this.Value * ((LongConstant)other).Value);
			if (other is IntegerConstant) return new LongConstant(this.Value * ((IntegerConstant)other).Value);
			if (other is DoubleConstant) return new DoubleConstant(this.Value * ((DoubleConstant)other).Value);
			if (other is FloatConstant) return new FloatConstant(this.Value * ((FloatConstant)other).Value);
			if (other is CharConstant) return new LongConstant(this.Value * ((CharConstant)other).Value);

			return base.Multiply(other);
		}

		public override Expression Divide(Constant other)
		{
			if (other is LongConstant && !other.IsZero) return new LongConstant(this.Value / ((LongConstant)other).Value);
			if (other is IntegerConstant && !other.IsZero) return new LongConstant(this.Value / ((IntegerConstant)other).Value);
			if (other is DoubleConstant && !other.IsZero) return new DoubleConstant(this.Value / ((DoubleConstant)other).Value);
			if (other is FloatConstant && !other.IsZero) return new FloatConstant(this.Value / ((FloatConstant)other).Value);
			if (other is CharConstant && !other.IsZero) return new LongConstant(this.Value / ((CharConstant)other).Value);

			return base.Divide(other);
		}

		public override Expression Modulo(Constant other)
		{
			if (other is LongConstant && !other.IsZero) return new LongConstant(this.Value % ((LongConstant)other).Value);
			if (other is IntegerConstant && !other.IsZero) return new LongConstant(this.Value % ((IntegerConstant)other).Value);
			if (other is DoubleConstant && !other.IsZero) return new DoubleConstant(this.Value % ((DoubleConstant)other).Value);
			if (other is FloatConstant && !other.IsZero) return new FloatConstant(this.Value % ((FloatConstant)other).Value);
			if (other is CharConstant && !other.IsZero) return new LongConstant(this.Value % ((CharConstant)other).Value); // there is something seriously wrong with you

			return base.Modulo(other);
		}

		public override Expression Negative()
		{
			return new LongConstant(-this.Value);
		}
	}
}
